/* Dynamic predicate for input facts. */
:-dynamic fact/1.

/* Dynamic predicate for tgd rules in the form (SkolemizedHead, Body, Head)*/
:-dynamic rule/3.


/* Index facts by variables. */
:- dynamic var_fact/2.


addFact(F) :-
	\+ fact(F)
	->
	(
	  assert(F),
	  assert(fact(F)),
	  index_fact(F)
	) ;
	true.

removeFact(F) :-
	retract(fact(F)),
	retract(F),
	de_index(F).

removeAllFacts(Pred, N) :-
	fact(F),
	functor(F, Pred, N),
	removeFact(F),
	fail.

removeAllFacts(Pred, N).

addFacts(','(A,B)) :-
	!,
	addFacts(A),
	addFacts(B).

addFacts(X) :-
	addFact(X).

addRule(SH, B, OH) :-
	assert(rule(SH, B, OH)).

removeRule(H,B, OH) :-
	retract(rule(H, B, OH)).

/*tell_constraint('<-'(H, B)) :- ( tell_egd(H,B) -> true ; tell_tgd('<-'(H,B)) ).*/
/*tell_constraint('->'(B,H)) :- tell_constraint('<-'(H,B)).*/
tell_tgd(:-(H, B)) :-
	tell_tgd('<-'(H, B)).



tell_tgd('<-'(H,B)) :-
	skolemize((H,B), (NH, NB, OH)),
	addRule(NH, NB, OH).



tell_tgd('->'(B,H)) :-
	tell_tgd('<-'(H, B)).

tell_tgd('<->'(H,B)) :-
	tell_tgd('<-'(H,B)),
	tell_tgd('->'(H,B)).

tell_tgd(H,B) :-
    tell_tgd('<-'(H,B)).



/*Dynamic predicate to store egds in the form (Body, VarList1, VarList2)*/
:- dynamic egd/3.



remove_egd(B, Vars1, Vars2) :-
	retractall(egd(B, Vars1, Vars2)).

process_egd(equal(X, Y), B):-
	assert(egd(B, X, Y)).

process_egd(','(equal(X,Y), Z), B) :-
	assert(egd(B, X, Y)),
	process_egd(Z, B).

tell_egd(:-(H, B)) :-
	tell_egd(H, B).
	
tell_egd('<-'(H,B)) :-
	tell_egd(H, B).

tell_egd('->'(B, H)) :-
    tell_egd(H, B).

tell_egd(H, B) :-
	process_egd(H, B).

/*Either an atom or a frozen constant.*/
constant(Term) :-
	atomic(Term), 
	!.

constant(Term) :-
	functor(Term, F, N),
	concat_atom([frozen, NAtom], '___', F),
	constant(N, Term).

constant(0, _).

constant(N, Term) :-
	N > 0,
	arg(N, Term, Arg),
	constant(Arg),
	N1 is N-1,
	constant(N1, Term).

countRule(X) :-
	assert(currentCount(0)),
	countRule,
	currentCount(X).

inc :-
	currentCount(C),
	C1 is C+1,
	retractall(currentCount(_)),
	assert(currentCount(C1)).

countRule :-
	rule(_, _, _),
	inc,
	fail.

countRule.

:- dynamic helper/1.

remove_helper(H) :-
  retractall(H),
  retract(helper(H)).

tell_helper(H) :-
  assert(H),
  assert(helper(H)).

/***********************************************************/
/*             Clearing Knowledge Base                     */
/***********************************************************/

/* Remove facts from the KB */
clearFacts :-
  fact(F),
  removeFact(F),
  fail.

clearFacts.

clearRules :-
  retractall(rule(_,_,_)),
  retractall(egd(_,_,_)).

clearHelpers :-
  helper(H),
  remove_helper(H),
  fail.

clearHelpers.

clearKnowledgeBase :-
   clearFacts,
   clearRules,
   clearHelpers.











